package rmsstream;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.IOException;

import javax.microedition.io.Connector;
import javax.microedition.io.ContentConnection;
import javax.microedition.media.Manager;
import javax.microedition.media.MediaException;
import javax.microedition.media.Player;
import javax.microedition.media.PlayerListener;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;
import javax.microedition.rms.RecordStoreFullException;
import javax.microedition.rms.RecordStoreNotFoundException;

import midlets.MediaPlayer;

public class RMSVideoPlayer implements Runnable, PlayerListener {

	public static final int STATUS_EMPTY = 0;
	public static final int STATUS_LOADING = 1;
	public static final int STATUS_WAITING = 2;
	public static final int STATUS_PLAYING = 3;
	public static final int STATUS_USED = 4;

	private int id_ = 0;
	private RMSBuffer buffer_ = null;
	VideoContentDescriptor vcd = null;

	private int STATUS = STATUS_EMPTY;
	private boolean finished_ = false;

	private byte contentData[];
	private ByteArrayInputStream contentByteArrayInputStream_ = null;

	private Player player_;

	public RMSVideoPlayer(RMSBuffer buffer, int id) {
		this.buffer_ = buffer;
		this.id_ = id;
	}

	public void start() {
		System.out
				.println("------------------STARTING Player Thread--------------------"
						+ this.id_);
		STATUS = STATUS_LOADING;
		Thread curThread = new Thread(this);
		curThread.start();
	}

	public void run() {
		STATUS = STATUS_LOADING;
		System.out.println("------------RMSVideoPlayer RUN--------------"
				+ this.id_);
		try {
			vcd = this.buffer_.getNextPlayable();
			if (vcd != null) {
				System.out.println("---------------- LOADING VIDEO ("
						+ vcd.getUrl_() + ")---------------- ");
				contentByteArrayInputStream_ = this.getContent(vcd.getUrl_());
				player_ = initPlayer();
				STATUS = STATUS_WAITING;
				System.out.println("----------Video (" + vcd.getUrl_()
						+ ") loaded-----------");
			} else {
				this.finished_ = true;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	// --------------------------------------------- PLAYER STUFF ---------

	public void play() {
		this.STATUS = STATUS_PLAYING;

		System.out.println("VIDEO" + this.id_
				+ "> -------------------- before Realize Player ---<");
		try {
			this.player_.realize();
		} catch (MediaException e) {
			e.printStackTrace();
		}
		System.out.println("VIDEO" + this.id_
				+ "> -------------------- before LoopCount Player ---<");
		this.player_.setLoopCount(-1); // play indefinitely
		System.out.println("VIDEO" + this.id_
				+ "> -------------------- before Prefetch Player ---<");
		try {
			this.player_.prefetch();
		} catch (MediaException e) { 
			e.printStackTrace();
		}
		System.out.println("VIDEO" + this.id_
				+ "> -------------------- after Prefetch Player ---<");

		VideoCanvas form = new VideoCanvas(this.player_);
		Thread newThread = new Thread(form);
		MediaPlayer.display.setCurrent(form);
		newThread.start();

	}

	public Player initPlayer() {

		Player player = null;
		try {
			System.out.println("VIDEO" + this.id_
					+ "> -------------------- before Create Player ---<");
			// player = Manager.createPlayer(contentByteArrayInputStream_,
			// this.vcd.getMime_());
			player = Manager
					.createPlayer(getInputStream(), this.vcd.getMime_());

			System.out
					.println("VIDEO"
							+ this.id_
							+ "> -------------------- before AddPlayerListener Player ---<");
			player.addPlayerListener(this);

		} catch (IOException e) {
			e.printStackTrace();
		} catch (MediaException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}

		return player;

	}

	public void playerUpdate(Player player, String event, Object eventData) {

		if (event.equals(PlayerListener.END_OF_MEDIA)) {
			this.buffer_.unregisterPlayer(this);
			this.STATUS = STATUS_USED;
		}

	}

	// -------------------- Load Content from URL and stores to Recordstore
	// ---------

	private ByteArrayInputStream getContent(String url) throws IOException,
			RecordStoreFullException, RecordStoreNotFoundException,
			RecordStoreException {
		ContentConnection connection = (ContentConnection) Connector.open(url);
		DataInputStream iStrm = connection.openDataInputStream();

		try {

			ByteArrayOutputStream bStrm = new ByteArrayOutputStream();
			int ch;
			while ((ch = iStrm.read()) != -1)
				bStrm.write(ch);
			contentData = bStrm.toByteArray();
			bStrm.close();
		} finally {
			if (iStrm != null)
				iStrm.close();
			if (connection != null)
				connection.close();
		}
		store();
		return (contentData == null ? null : new ByteArrayInputStream(
				contentData));
	}

	public void store() throws RecordStoreFullException,
			RecordStoreNotFoundException, RecordStoreException {

		if (contentData != null) {
			RecordStore rs = RecordStore.openRecordStore(
					"videofile" + this.id_, true);
			System.out.println("RECORDSTORE> Available "
					+ rs.getSizeAvailable() + " and needed "
					+ contentData.length);

			int i = 1;
			while (rs.getSizeAvailable() < contentData.length) {
				rs.deleteRecord(i);
				i++;
			}

			rs.addRecord(contentData, 0, contentData.length);
		}
	}

	// --------------------------- Load Content from Recordstore ---------

	public ByteArrayInputStream getInputStream() throws Exception {
		System.out.println("STATUS " + STATUS);

		RecordStore rs = RecordStore.openRecordStore("videofile" + this.id_,
				false);
		System.out.println("AAAAAAAAAAAAA");
		return new ByteArrayInputStream(rs.getRecord(1));

	}

	// --------------------------- Getters and Setters ---------

	public int getSTATUS() {
		return STATUS;
	}

	public ByteArrayInputStream getContentByteArrayInputStream_() {
		return contentByteArrayInputStream_;
	}

	public boolean isFinished_() {
		return finished_;
	}

}
